package nl.utwente.ewi.hmi.multitouch;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;

import nl.utwente.ewi.hmi.multitouch.io.TouchStreamProvider;
import nl.utwente.ewi.hmi.multitouch.io.TouchStreamProviderLocator;

public class TouchStreamProviderFactory {

	private static final Logger log = Logger.getLogger(TouchStreamProviderFactory.class.getName());

	private static final String PROPERTIES_FILE = "mu3.properties";
	
	private static final Set<TouchStreamProviderLocator> locators;
	
	static {
		locators = new HashSet<TouchStreamProviderLocator>();
		init();
	}
	
	private static void init() {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		URL url = classLoader.getResource(PROPERTIES_FILE);

		if(url == null) {
			log.warning(String.format("Resource \"%s\" could not be located, falling back to default properties.", PROPERTIES_FILE));
			return;
		}

		File file ;
		try {
			file = new File(url.toURI());
		} catch (URISyntaxException e) {
			log.warning(String.format("Resource \"%s\" has an invalid URI, falling back to default properties.", PROPERTIES_FILE));
			return;
		}

		if(!file.canRead()) {
			log.warning(String.format("Resource \"%s\" could not be read, falling back to default properties.", PROPERTIES_FILE));
			return;
		}

		
		Properties properties = new Properties();

		try {
			properties.load(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			log.warning(String.format("Resource \"%s\" could not be read, falling back to default properties.", PROPERTIES_FILE));
			return;
		} catch (IOException e) {
			log.warning(String.format("Resource \"%s\" could not be read, falling back to default properties.", PROPERTIES_FILE));
			return;
		}
		
		String locators = properties.getProperty("mu3.locators", "");
		
		if(! locators.equals("")) {
			String[] locatorsArr = locators.split(",");
			for(String locator : locatorsArr) {
				Class<?> locatorClass = null;
				System.out.println(locator);
				try {
					locatorClass = Class.forName(locator.trim(), true, classLoader);
				} catch (ClassNotFoundException e) {
					continue;
				}

				if(!TouchStreamProviderLocator.class.isAssignableFrom(locatorClass)) {
					continue;
				}
				
				TouchStreamProviderLocator locatorInstance;
				try {
					locatorInstance = (TouchStreamProviderLocator) locatorClass.newInstance();
				} catch (InstantiationException e) {
					continue;
				} catch (IllegalAccessException e) {
					continue;
				}
				
				TouchStreamProviderFactory.locators.add(locatorInstance);
			}
		}
		
	}

	public static TouchStreamProvider getTouchStreamProvider(URI uri) {
		TouchStreamProvider provider = null;
		Iterator<TouchStreamProviderLocator> locatorIterator = locators.iterator();

		while(provider == null && locatorIterator.hasNext()) {
			TouchStreamProviderLocator locator = locatorIterator.next();
			if(locator.validTouchStreamProvider(uri)) {
				provider = locator.locateTouchStreamProvider(uri);
			}
		}

		return provider;
	}
}
